package com.distribute.framework.core.apt;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Pattern;

public abstract class TplBase implements java.io.Serializable{
	private static final long serialVersionUID = -1L;
	public String filename = null;
	public TplOut out=new TplOut();
	public BaseIO io;
	public Map<String,Object> params;
	
	public static List objectToArray(Object object){
		if(object==null)return null;
		List list = new ArrayList();
		list.add(object.getClass().getSimpleName());
		for(Field field:object.getClass().getDeclaredFields()){
			field.setAccessible(true);
			Object value = null;
			try {
				value = field.get(object);
			} catch ( Exception e) {
				e.printStackTrace();
			}
			if(value==null){
				list.add(null);
			}else if(value instanceof List){
				List lst=new ArrayList();
				List arr = (List) value;
				for(Object obj:arr){
					lst.add(objectToArray(obj));
				}
				list.add(lst);
			}else{
				list.add(value);
			}
		}
		return list;
	}
	
	public Set<Entry<String, Object>> entrys(Object value){
		Map<String,Object> map = (Map) value;
		List<Map.Entry> list = new ArrayList();
		return map.entrySet();
	}
	
	public String kv(String key,String tmpl){
		return kv(key,tmpl,null);
	}
	public String kv(String key,String tmpl,String defaultValue){
		Object value = params.get(key);
		if(value==null){
			return defaultValue==null?"":defaultValue;
		}
		return tmpl.replace("{key}", key).replace("{value}", value.toString());
	}
	public String $(String key){
		Object value = params.get(key);
		if(value==null){
			return "";
		}
		return value.toString();
	}
	
	public static String hashcode(String str){
		return ""+Math.abs(str.hashCode());
	}
	
	public static Boolean empty(String string)
	{
		return string==null || string.trim().equals("");
	}
	
	public static String or(String a, String b) {
		if ((a == null) || (a.trim().equals("")))
			return b;
		return a.trim();
	}
	
	public static String stype(String string)
	{
		if(string==null || string.equals(""))
			return "";
		return string.substring(string.lastIndexOf(".")+1);
	}
	
	public static String pkg(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\\\", "/").replaceAll("/", ".");
		if(string.charAt(0)=='.')
			string=string.substring(1);
		return string;
	}
	
	public static String dpkg(String string)
	{		
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\\\", "/").replaceAll("/", ".");
		if(string.charAt(0)=='.')
			string=string.substring(1);
		return "."+string;
	}
	
	public static String pkgd(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\\\", "/").replaceAll("/", ".");
		if(string.charAt(0)=='.')
			string=string.substring(1);
		return string+".";
	}
	
	public static String path(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\.", "/").replaceAll("\\\\", "/");
		if(string.charAt(0)=='/')
			string=string.substring(1);
		return string;
	}
	
	public static String gpath(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\.", "/").replaceAll("\\\\", "/");
		if(string.charAt(0)=='/')
			string=string.substring(1);
		return "/"+string;
	}
	
	public static String pathg(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\.", "/").replaceAll("\\\\", "/");
		if(string.charAt(0)=='/')
			string=string.substring(1);
		return string+"/";
	}
	
	public static String pathddg(String string)
	{
		if(string==null || string.equals(""))
			return "";
		string=string.replaceAll("\\.", "/").replaceAll("\\\\", "/");
		if(string.charAt(0)=='/')
			string=string.substring(1);
		string = string+"/";
		string = string.replaceAll("[a-zA-Z0-9_$]+", "..");
		return string;
	}
	
	
	
	public static Integer INT(String string){
		Integer i=0;
		try{
			i=Integer.parseInt(string);
		}catch(Exception ex){
			
		}
		return i==null?0:i;
	}
	
	public static String letter(String string)
	{
		if(string==null || string.equals(""))
			return string;
		return string.replaceAll("[^a-zA-Z]+", "");
	}
	
	/**
	 * 对齐4字符
	 * @param string
	 * @return
	 */
	public static String align(String string)
	{
		if(string==null || string.equals(""))
			return string;
		if(string.length()<=1||string.length()>=4)
			return string;
		String newString = "";
		if(string.length()==2)
			newString=string.charAt(0)+"　　"+string.charAt(1);
		if(string.length()==3)
			newString=string.charAt(0)+" "+string.charAt(1)+" "+string.charAt(2);
		return newString;
	}
	
	/**
	 * 根据名称取子级前缀
	 * @param name  父名子
	 * @param bParentPrefix 是否包含父级前缀
	 * @return
	 */
	public static String tumb(String name,boolean bParentPrefix)
	{		
		String strPrefix="";
		Boolean _=true;
		for(int i=0;i<name.length();i++)
		{
			String ch=""+name.charAt(i);
			if(ch.equals("_"))
			{
				_=true;
			}
			else
			{
				if(_){
					strPrefix+=ch.toLowerCase();
				}							
				_=false;
			}			
		}
		
		if(bParentPrefix && name.indexOf("_")>0){
			String sParentPrefix=name.substring(0, name.indexOf("_"));
			strPrefix=sParentPrefix+strPrefix.substring(1);
		}
		
		return strPrefix;
	}
	
	/**
	 * 把数据库字段转成java格式的
	 * @param name
	 * @return
	 */
	public static String java(String name)
	{		
		String upName="";
		Boolean _=false;
		for(int i=0;i<name.length();i++)
		{
			String ch=""+name.charAt(i);
			if(ch.equals("_"))
			{
				_=true;
			}
			else
			{
				if(_){
					upName+=ch.toUpperCase();
				}
				else{
					upName+=ch;
				}				
				_=false;
			}			
		}
		return upName;
	}
	
	public static String fmt(String string)
	{
		if(string==null || string.equals(""))
			return string;
		return tumb(string,true);
	}
		
	/**
	 * 1、如果属性名的第二个字母大写，那么该属性名直接用作 getter/setter 方法中 get/set 的后部分，就是说大小写不变。例如属性名为uName，方法是getuName/setuName。
	 * 2、如果前两个字母是大写（一般的专有名词和缩略词都会大写），也是属性名直接用作 getter/setter 方法中 get/set 的后部分。例如属性名为URL，方法是getURL/setURL。
	 * 3、如果首字母大写，也是属性名直接用作 getter/setter 方法中 get/set 的后部分。例如属性名为Name，方法是getName/setName，这种是最糟糕的情况，会找不到属性出错，因为默认的属性名是name。
	 * 总结:如果前两个字母有大写，则直接返回
	 * @param string
	 * @return
	 */
	public static String ForMater(String string){
		if(string.length()>2 && Pattern.compile("[A-Z]").matcher(string.substring(0, 2)).find())
			return string;		
		return ForMat(string);
	}
	
	
	public static String ForMat(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = java(string);
		return string.substring(0,1).toUpperCase() + string.substring(1);
	}
	
	public static String forMat(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = java(string);
		return string.substring(0,1).toLowerCase() + string.substring(1);
	}
	
	public static String Mat(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = forMat(string);
		String[] arr = string.replaceAll("([A-Z])", "_$1").split("_");
		return arr[arr.length-1];
	}
	
	public static String MAT(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = Mat(string);
		return string.toUpperCase();
	}
	
	public static String mat(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = Mat(string);
		return string.toLowerCase();
	}
	
	
	public static String format(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = java(string);
		return string.toLowerCase();		
	}
	
	public static String FORMAT(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = java(string);
		return string.toUpperCase();		
	}
	
	public static String Format(String string)
	{
		if(string==null || string.equals(""))
			return string;
		string = java(string);
		string=string.toLowerCase();
		return string.substring(0,1).toUpperCase() + string.substring(1);
	}
	
	public  int find(String filename,String string)
	{
		/*String xmlString=file(filename);		
		return xmlString.indexOf(string);*/
		return io.find(filename,string);
	}
	
	public  Boolean insert(String filename,String srcReg,String replace)
	{
		/*String xmlString=file(filename);		
		Pattern pattern = Pattern.compile(srcReg);
		Matcher matcher = pattern.matcher(xmlString);
		if(matcher.find()){
			xmlString=xmlString.replaceAll(srcReg,replace);
			write(filename,xmlString);
			return true;
		}
		else
			return false;*/
		return io.insert(filename,srcReg,replace);
	}
	
	public void append(String filename,String string)
	{
		/*String xmlString=file(filename);	
		xmlString+=string;
		write(filename,xmlString);*/
		io.append(filename,string);
	}
	
	/**
     * @notes 字符串转化为十六进制字符串
     * @param bytes
     * @return String
     */
    public static String x(String a) {
    	if(empty(a))
    		return "";
    	String b = "";
    	for(int i=0;i<a.length();i+=4){
    		String d = a.substring(i,i+4);
    		int c = Integer.valueOf(d, 16);
    		c = c-23;
    		b+=(char)c;
    	}
    	b = b.replaceAll("\\n", "\n");
        return b;
    }
	
	/*public String file(String filename,String encode)
	{
		return io.readFile(filename,encode);
	}
	
	public String file(String filename)
	{
		return io.readFile(filename,"UTF-8");
	}*/
	
	public void write(String filename,String content,String encode){
		io.writeFile(filename,content,encode);
	}
	public void write(String filename,String content)
	{
		write(filename,content,"UTF-8");
	}
	
	public void complete()
	{
		String fileName=this.getFilename();		
		try{
			if(fileName!=null && !fileName.equals("")){
				io.writeFile(fileName,this.out.getContent().trim(),"UTF-8");
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
		
		List<StringBuffer> contents = out.getContents();
		if(contents.size()==1)
			return;
		for(int i=1;i<contents.size();i++)
		{
			String strFollow=contents.get(i).toString();			
			try{
				Method method = this.getClass().getMethod("$"+i+"_follow",String.class);
				if(method!=null)
					method.invoke(this,strFollow);
			}catch (Exception ex) {
				throw new RuntimeException(ex);
			}
		}
		out.destory();
	}
	
	public BaseIO getIo() {
		return io;
	}

	public void setIo(BaseIO io) {
		this.io = io;
	}

	public TplOut getOut() {
		return out;
	}

	public void setOut(TplOut out) {
		this.out = out;
	}

	public abstract void execute(BaseIO baseIO,Map<String,Object> params);
	
	
	public static class TplOut
	{
		private List<StringBuffer> contents=new ArrayList();
		private int index=0;
		
		private void write(String string)
		{
			if(contents.size()-1<index)
				contents.add(new StringBuffer());			
			StringBuffer sb=contents.get(index);		
			sb.append(string);
		}
		
		private void newLine()
		{
			if(contents.size()-1<index)
				contents.add(new StringBuffer());			
			StringBuffer sb=contents.get(index);		
			sb.append("\n");
		}
		
		public String getContent(){
			if(contents==null)return null;
			if(contents.size()==0)return null;
			if(contents.get(0)==null)return null;		
			return contents.get(0).toString();
		}

		public void setIndex(int index){
			this.index = index;
		}

		public List<StringBuffer> getContents()
		{
			return contents;
		}
		
	    public void print(boolean b) {
	    	write(b ? "true" : "false");
	    }

		public void print(char c) {
			write(String.valueOf(c));
	    }

	    public void print(int i) {
	    	write(String.valueOf(i));
	    }

	    public void print(long l) {
	    	write(String.valueOf(l));
	    }

	    public void print(float f) {
	    	write(String.valueOf(f));
	    }

	    public void print(double d) {
	    	write(String.valueOf(d));
	    }

	    public void print(char s[]) {
	    	write(new String(s));
	    }

	    public void print(String s) {
			if (s == null) {
			    s = "null";
			}
			write(s);
	    }

	    public void print(Object obj) {
	    	write(String.valueOf(obj));
	    }

	
	    /* Methods that do terminate lines */
	    public void println() {
	    	newLine();
	    }

	    public void println(boolean x) {
		    print(x);
		    newLine();
	    }

	    public void println(char x) {
		    print(x);
		    newLine();
	    }

	    public void println(int x) {	
		    print(x);
		    newLine();
		}

	    public void println(long x) {	
		    print(x);
		    newLine();
		}

	    public void println(float x) {	
		    print(x);
		    newLine();
		}

	    public void println(double x) {	
		    print(x);
		    newLine();
		}

	    public void println(char x[]) {	
		    print(x);
		    newLine();
		}

	    public void println(String x) {	
		    print(x);
		    newLine();
		}

	    public void println(Object x) {
		    print(x);
		    newLine();
		}

		public void destory(){
			contents.clear();
			contents=null;
		}
	}



	public String getFilename() {
		return filename;
	}

	public void setFilename(String filename) {
		this.filename = filename;
	}

	public Map<String,Object> getParams() {
		return params;
	}

	public void setParams(Map<String,Object> params) {
		this.params = params;
	}

}